﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

namespace Star.Tools.Helper
{
    /// <summary>
    /// 枚举 操作
    /// </summary>
    public static class EnumHelper
    {

        #region # 常量
        /// <summary>
        /// 枚举值字段
        /// </summary>
        private const string EnumValueField = "value__";

        #endregion

        /// <summary>
        /// 验证是否枚举类型
        /// </summary>
        public static void ValidationIsEnum(Type enumType)
        {
            if (enumType.IsEnum == false)
                throw new InvalidOperationException(string.Format("类型 {0} 不是枚举", enumType));
        }

        #region 获取枚举描述
        /// <summary>
        /// 获取当前枚举描述description
        /// </summary>
        /// <param name="enum"></param>
        /// <returns></returns>
        public static string ToDescriptionString(this object @enum)
        {

            var attribute = @enum.GetType().GetField(@enum.ToString()).
            GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
            return attribute == null ? @enum.ToString() : ((DescriptionAttribute)attribute).Description;

        }
        /// <summary>
        ///  获取当前枚举指定描述description
        /// </summary>
        /// <param name="enum"></param>
        /// <param name="enumname"></param>
        /// <returns></returns>
        public static string ToDescriptionString(this Enum @enum, string enumname)
        {
            try
            {
                var attribute = @enum.GetType().GetField(enumname).
                    GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
                return attribute == null ? @enum.ToString() : ((DescriptionAttribute)attribute).Description;
            }
            catch
            {
                return null;
            }
        }
        public static string GetDescription(Enum obj)
        {
            if (obj == null)
            {
                return String.Empty;
            }
            //string objName = obj.ToString();
            //Type t = obj.GetType();
            FieldInfo fi = obj.GetType().GetField(obj.ToString());
            DescriptionAttribute[] arrDesc = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), true);
            if (arrDesc.Length == 0)
            {
                return obj.ToString();
            }
            return arrDesc[0].Description;
        }
        /// <summary>
        /// 获取枚举成员名称
        /// </summary>
        /// <param name="enum">枚举值</param>
        /// <returns>枚举成员名称</returns>
        public static string GetEnumMember(this Enum @enum)
        {
            Type type = @enum.GetType();
            FieldInfo field = type.GetField(@enum.ToString());
            DescriptionAttribute enumMember = field.GetCustomAttribute<DescriptionAttribute>();
            return enumMember == null ? @enum.ToString()
                : string.IsNullOrEmpty(enumMember.Description) ? @enum.ToString() :
                enumMember.Description;
        }
        #endregion

        #region # 获取枚举成员名称字典 
        ///<summary>
        /// 返回 Dic 枚举项，描述  
        ///</summary>
        ///<param name="enumType"></param>
        ///<returns>Dic枚举项，描述</returns>
        public static Dictionary<string, string> GetEnumsDescription(Type enumType)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            FieldInfo[] fieldinfos = enumType.GetFields();
            foreach (FieldInfo field in fieldinfos)
            {
                if (field.FieldType.IsEnum)
                {
                    string text = field.GetCustomAttribute<DescriptionAttribute>() is DescriptionAttribute attribute ? attribute.Description : field.Name;

                    //object[] objs = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
                    //string text = objs.Length > 0 ? (string.IsNullOrEmpty(((DescriptionAttribute)objs[0]).Description) ? field.Name
                    //    : ((DescriptionAttribute)objs[0]).Description)
                    //    : field.Name;

                    dic.Add(field.Name, text);
                }

            }

            return dic;
        }
      
        /// <summary>
        /// 获取枚举成员名称字典
        /// </summary>
        /// <param name="enumType">枚举类型</param>
        /// <returns>枚举成员名称字典</returns>
        /// IDictionary[string, string]，[枚举名，枚举描述]
        public static IDictionary<string, string> GetEnumMembers(this Type enumType)
        {
            #region # 验证参数

            if (!enumType.IsSubclassOf(typeof(Enum)))
            {
                throw new ArgumentOutOfRangeException(string.Format("类型\"{0}\"不是枚举类型！", enumType.Name));
            }

            #endregion

            FieldInfo[] fields = enumType.GetFields();

            IDictionary<string, string> dictionaries = new Dictionary<string, string>();

            foreach (FieldInfo field in fields.Where(x => x.Name != EnumValueField))
            {
                DescriptionAttribute enumMember = field.GetCustomAttribute<DescriptionAttribute>();

                dictionaries.Add(field.Name, enumMember == null ? field.Name : string.IsNullOrEmpty(enumMember.Description) ? field.Name : enumMember.Description);
            }

            return dictionaries;
        }
        #endregion

      

        #region 枚举型相关操作

        /// <summary>
        /// 功能描述；获取枚举名称.传入枚举类型和枚举值
        /// </summary>
        /// <param name="enumType"></param>
        /// <param name="intEnumValue"></param>
        /// <returns></returns>
        public static string GetEnumText<T>(int intEnumValue)
        {
            return Enum.GetName(typeof(T), intEnumValue);
        }
        #endregion


        /// <summary>
        /// 功能描述:获取枚举项集合，传入枚举类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IList<object> GetEnumsList<T>()
        {
            IList<object> _list = new List<object>();
            //遍历枚举集合
            foreach (int i in Enum.GetValues(typeof(T)))
            {
                var _selItem = new
                {
                    Key = Enum.GetName(typeof(T), i),
                    Value = i,

                };
                _list.Add(_selItem);
            }
            return _list;
        }




        /////<summary>
        /////</summary>
        //public static List<EnumsClass> BindEnumsList(Type enumType)
        //{
        //    var list = new List<EnumsClass>();
        //    FieldInfo[] fieldinfos = enumType.GetFields();
        //    var enumvalue = Enum.GetValues(enumType);
        //    foreach (FieldInfo field in fieldinfos)
        //    {
        //        if (field.FieldType.IsEnum)
        //        {
        //            int ev = -1;
        //            Object[] objs = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
        //            foreach (int item in enumvalue)
        //            {
        //                if (Enum.GetName(enumType, item) == field.Name)
        //                {
        //                    ev = item;
        //                    break;
        //                }
        //            }
        //            list.Add(new EnumsClass
        //            {
        //                Name = field.Name,
        //                Value = ev,
        //                Text = ((DescriptionAttribute)objs[0]).Description
        //            });
        //        }
        //    }
        //    return list;
        //}





     
        #region # 获取枚举成员名称 
      
        #endregion

        

        #region # 将字符串转换成可空的枚举 —— static T? GetEnum<T>(this string enumStr)
        /// <summary>
        /// 将字符串转换成可空的枚举
        /// </summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <param name="enumStr">枚举的字符串值</param>
        /// <returns>可空的枚举值</returns>
        public static T? GetEnum<T>(this string enumStr) where T : struct
        {
            #region # 验证参数

            if (string.IsNullOrWhiteSpace(enumStr))
            {
                return null;
            }
            if (typeof(T).IsSubclassOf(typeof(Enum)))
            {
                throw new ArgumentOutOfRangeException(string.Format("类型\"{0}\"不是枚举类型！", typeof(T).Name));
            }

            #endregion

            T @enum;

            if (!Enum.TryParse(enumStr, out @enum))
            {
                throw new InvalidCastException(string.Format("无法将给定字符串\"{0}\"转换为枚举\"{1}\"！", enumStr, typeof(T).Name));
            }

            return @enum;
        }
        #endregion

        #region # 获取枚举类型完整信息 —— static ICollection<Tuple<int, string, string>> GetEnumMemberInfos(...
        /// <summary>
        /// 获取枚举类型完整信息
        /// </summary>
        /// <param name="enumType">枚举类型</param>
        /// <returns>完整信息</returns>
        /// <remarks>
        /// Tuple[int, string, string]，[枚举int值，枚举名，枚举描述]
        /// </remarks>
        public static ICollection<Tuple<int, string, string>> GetEnumMemberInfos(this Type enumType)
        {
            #region # 验证参数

            if (!enumType.IsSubclassOf(typeof(Enum)))
            {
                throw new ArgumentOutOfRangeException(string.Format("类型\"{0}\"不是枚举类型！", enumType.Name));
            }

            #endregion

            FieldInfo[] fields = enumType.GetFields();

            ICollection<Tuple<int, string, string>> enumInfos = new HashSet<Tuple<int, string, string>>();

            foreach (FieldInfo field in fields.Where(x => x.Name != EnumValueField))
            {
                DescriptionAttribute enumMember = field.GetCustomAttribute<DescriptionAttribute>();
                int value = Convert.ToInt32(field.GetValue(Activator.CreateInstance(enumType)));

                enumInfos.Add(new Tuple<int, string, string>(value, field.Name, enumMember == null ? field.Name : string.IsNullOrEmpty(enumMember.Description) ? field.Name : enumMember.Description));
            }

            return enumInfos;
        }
        #endregion

        #region # 获取枚举值、描述字典 —— static IDictionary<int, string> GetEnumDictionary(...
        /// <summary>
        /// 获取枚举值、描述字典
        /// </summary>
        /// <param name="enumType">枚举类型</param>
        /// <returns>枚举值、描述字典</returns>
        /// IDictionary[int, string]，[枚举int值，枚举描述]
        public static IDictionary<int, string> GetEnumDictionary(this Type enumType)
        {
            IEnumerable<Tuple<int, string, string>> tuples = GetEnumMemberInfos(enumType);

            IDictionary<int, string> dictionary = new Dictionary<int, string>();
            foreach (Tuple<int, string, string> tuple in tuples)
            {
                dictionary.Add(tuple.Item1, tuple.Item3);
            }

            return dictionary;
        }
        #endregion

        ///// <summary>
        ///// 获取枚举定义列表
        ///// </summary>
        ///// <param name="type">枚举类型</param>
        //public static List<(string Name, int Value, string DisplayName, string Description)> GetEnumDefinitionList(
        //    this Type type)
        //{
        //    var list = new List<(string Name, int Value, string DisplayName, string Description)>();
        //    var attributeType = type;
        //    if (!attributeType.IsEnum)
        //        return null;
        //    var names = Enum.GetNames(attributeType);
        //    var values = Enum.GetValues(attributeType);
        //    var index = 0;
        //    foreach (var value in values)
        //    {
        //        var name = names[index];
        //        var field = value.GetType().GetField(values.ToString());
        //        var displayName = field.GetDisplayName();
        //        var desc = field.GetDescription();
        //        (string Name, int Value, string DisplayName, string Description) item = (name, Convert.ToInt32(value),
        //            string.IsNullOrWhiteSpace(displayName) ? null : displayName,
        //            string.IsNullOrWhiteSpace(desc) ? null : desc);
        //        list.Add(item);
        //        index++;
        //    }

        //    return list;
        // }

    }
}
